﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace RouteEditor
{
    public partial class RouteTimeline : UserControl
    {
        TimeSpan timeToShow = TimeSpan.Zero;
        HighlightInfo highlightInfo;

        public RouteTimeline()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
        }

        public TimeSpan TimeToShow
        {
            get { return timeToShow; }
            set { timeToShow = value; Invalidate(); }
        }

        public void Highlight(HighlightInfo highlightInfo)
        {
            this.highlightInfo = highlightInfo;
            Refresh();
        }

        Pen linePen = new Pen(Color.Blue, 1);
        Brush highlightBrush = new SolidBrush(Color.FromArgb(100, Color.Gray));
        Brush textBrush = new SolidBrush(Color.Orange);
        
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            if (timeToShow == TimeSpan.Zero)
                return;

            int width = this.ClientRectangle.Width;
            int height = this.ClientRectangle.Height;

            double minutesPerPixel = (double)width / timeToShow.TotalMinutes;

            Graphics g = e.Graphics;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;

            g.DrawLine(linePen, new Point(0, height/2), new Point(width, height/2));

            if (highlightInfo == null)
                return;

            DrawHighlight(width, height, minutesPerPixel, g);
        }

        Font descriptionFont = new Font("Tahoma", 12, FontStyle.Bold);
        Font textFont = new Font("Tahoma", 7, FontStyle.Bold);

        private void DrawHighlight(int width, int height, double minutesPerPixel, Graphics g)
        {
            int x = (int)Math.Round(highlightInfo.Start.TotalMinutes * minutesPerPixel);
            int rectWidth = GetHighlightDuration(minutesPerPixel);

            g.FillRectangle(highlightBrush, new RectangleF(x, 0, rectWidth, height));

            // Draw description
            RectangleF descriptionRect = CalculateLocation(highlightInfo.Description, g, descriptionFont,
                textSize => new PointF(x + rectWidth / 2 - textSize.Width / 2, height / 2 - textSize.Height/2 - 5));
            AdjustTextLocations(ref descriptionRect, width);

            g.DrawString(highlightInfo.Description, descriptionFont, textBrush, descriptionRect.Location);
            
            RectangleF startTextRect = CalculateLocation(highlightInfo.StartText, g, textFont, textSize => new PointF(x - textSize.Width, height-  textSize.Height));
            RectangleF endTextRect = CalculateLocation(highlightInfo.EndText, g, textFont, textSize => new PointF(x + rectWidth, height - textSize.Height));

            AdjustTextLocations(ref startTextRect, ref endTextRect, width);

            g.DrawString(highlightInfo.StartText, textFont, textBrush, startTextRect.Location);
            g.DrawString(highlightInfo.EndText, textFont, textBrush, endTextRect.Location);
        }

        private void AdjustTextLocations(ref RectangleF startTextRect, ref RectangleF endTextRect, int totalWidth)
        {
            if (startTextRect.Right > endTextRect.Left)
                startTextRect.X = endTextRect.Left - startTextRect.Width;

            if (endTextRect.Right > totalWidth)
            {
                endTextRect.X -= (endTextRect.Right - totalWidth);

                if (startTextRect.Right > endTextRect.Left)
                    startTextRect.X = endTextRect.Left - startTextRect.Width;
            }
            if (startTextRect.Left < 0)
            {
                startTextRect.X = 0;

                if (startTextRect.Right > endTextRect.Left)
                    endTextRect.X = startTextRect.Left + startTextRect.Width;
            }
        }

        private void AdjustTextLocations(ref RectangleF textRect, int totalWidth)
        {
            if (textRect.Right > totalWidth)
            {
                textRect.X -= (textRect.Right - totalWidth);
            }
            if (textRect.Left < 0)
            {
                textRect.X = 0;
            }
        }

        private RectangleF CalculateLocation(string text, Graphics g, Font font, Func<SizeF, PointF> textSizeToLocationConverter)
        {
            SizeF textSize = g.MeasureString(text, font);
            PointF textLocation = textSizeToLocationConverter(textSize);

            return new RectangleF(textLocation, textSize);
        }

        private int GetHighlightDuration(double minutesPerPixel)
        {
            return (int)Math.Round(highlightInfo.Duration == TimeSpan.Zero ? minutesPerPixel : highlightInfo.Duration.TotalMinutes * minutesPerPixel);
        }

        private void RouteTimeline_Layout(object sender, LayoutEventArgs e)
        {
            Invalidate();
        }
    }

    public class HighlightInfo
    {
        public TimeSpan Start { get; set; }
        public TimeSpan Duration { get; set; }
        public string Description { get; set; }
        public string StartText { get; set; }
        public string EndText { get; set; }
    }
}
